package com.pan.test.controller;

import com.pan.test.component.RedisComponent;
import com.pan.test.entity.config.AppConfig;
import com.pan.test.entity.constants.Constants;
import com.pan.test.entity.dto.DownloadFileDto;
import com.pan.test.entity.enums.FileCategoryEnums;
import com.pan.test.entity.enums.FileFolderTypeEnums;
import com.pan.test.entity.enums.ResponseCodeEnum;
import com.pan.test.entity.po.FileInfo;
import com.pan.test.entity.query.FileInfoQuery;
import com.pan.test.entity.vo.FolderVO;
import com.pan.test.entity.vo.ResponseVO;
import com.pan.test.exception.BusinessException;
import com.pan.test.service.FileInfoService;
import com.pan.test.service.OSSService;
import com.pan.test.utils.CopyTools;
import com.pan.test.utils.StringTools;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;

@RestController
@RequestMapping("/common/file")
public class CommonFileController extends ABaseController {
    private static final Logger logger = LoggerFactory.getLogger(CommonFileController.class);

    @Resource
    protected FileInfoService fileInfoService;

    @Resource
    protected AppConfig appConfig;

    @Resource
    private RedisComponent redisComponent;

    @Resource
    private OSSService ossService;

    @GetMapping("/getFolderInfo")
    public ResponseVO getFolderInfo(@RequestParam String path, @RequestParam String userId) {
        String[] pathArray = path.split("/");
        FileInfoQuery infoQuery = new FileInfoQuery();
        infoQuery.setUserId(userId);
        infoQuery.setFolderType(FileFolderTypeEnums.FOLDER.getType());
        infoQuery.setFileIdArray(pathArray);
        String orderBy = "field(file_id,\"" + StringUtils.join(pathArray, "\",\"") + "\")";
        infoQuery.setOrderBy(orderBy);
        List<FileInfo> fileInfoList = fileInfoService.findListByParam(infoQuery);
        return getSuccessResponseVO(CopyTools.copyList(fileInfoList, FolderVO.class));
    }

    @GetMapping("/getImage/**")
    public void getImage(HttpServletResponse response, HttpServletRequest request) {
        String path = request.getRequestURI();
        String[] pathArray = path.split("/getImage/");
        if (pathArray.length != 2) {
            return;
        }
        String objectName = pathArray[1];
        try (InputStream inputStream = ossService.downloadFile(objectName)) {
            if (inputStream == null) {
                logger.error("获取图片失败，文件不存在：{}", objectName);
                return;
            }
            String imageSuffix = StringTools.getFileSuffix(objectName);
            imageSuffix = imageSuffix.replace(".", "");
            String contentType = "image/" + imageSuffix;
            response.setContentType(contentType);
            response.setHeader("Cache-Control", "max-age=2592000");
            IOUtils.copy(inputStream, response.getOutputStream());
        } catch (Exception e) {
            logger.error("获取图片失败", e);
        }
    }

    @GetMapping("/getFile")
    protected void getFile(HttpServletResponse response,
                         @RequestParam("fileId") String fileId,
                         @RequestParam("userId") String userId) {
        FileInfo fileInfo = fileInfoService.getFileInfoByFileIdAndUserId(fileId, userId);
        if (fileInfo == null) {
            return;
        }
        
        try (InputStream inputStream = ossService.downloadFile(fileInfo.getFilePath())) {
            if (inputStream == null) {
                logger.error("下载文件失败，文件不存在：{}", fileInfo.getFilePath());
                return;
            }
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileInfo.getFileName(), "UTF-8"));
            IOUtils.copy(inputStream, response.getOutputStream());
        } catch (Exception e) {
            logger.error("下载文件失败", e);
        }
    }

    @GetMapping("/createDownloadUrl")
    protected ResponseVO createDownloadUrl(@RequestParam("fileId") String fileId,
                                         @RequestParam("userId") String userId) {
        FileInfo fileInfo = fileInfoService.getFileInfoByFileIdAndUserId(fileId, userId);
        if (fileInfo == null) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        if (FileFolderTypeEnums.FOLDER.getType().equals(fileInfo.getFolderType())) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        String code = StringTools.getRandomString(Constants.LENGTH_50);
        DownloadFileDto downloadFileDto = new DownloadFileDto();
        downloadFileDto.setDownloadCode(code);
        downloadFileDto.setFilePath(fileInfo.getFilePath());
        downloadFileDto.setFileName(fileInfo.getFileName());

        redisComponent.saveDownloadCode(code, downloadFileDto);

        return getSuccessResponseVO(code);
    }

    @GetMapping("/download")
    protected void download(HttpServletRequest request,
                          HttpServletResponse response,
                          @RequestParam("code") String code) throws Exception {
        DownloadFileDto downloadFileDto = redisComponent.getDownloadCode(code);
        if (null == downloadFileDto) {
            return;
        }
        
        try (InputStream inputStream = ossService.downloadFile(downloadFileDto.getFilePath())) {
            if (inputStream == null) {
                logger.error("下载文件失败，文件不存在：{}", downloadFileDto.getFilePath());
                return;
            }
            String fileName = downloadFileDto.getFileName();
            response.setContentType("application/octet-stream");
            
            if (request.getHeader("User-Agent").toLowerCase().indexOf("msie") > 0) {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } else {
                fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
            }
            
            response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
            IOUtils.copy(inputStream, response.getOutputStream());
        } catch (Exception e) {
            logger.error("下载文件失败", e);
        }
    }
}
